﻿/*  CamHelper (See http://camhelper.codeplex.com/ or https://bitbucket.org/AndiKS/camhelper for more Info)
    Copyright (C) 2011 Andreas Wimmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using CamHelper.Interpreter;
using NUnit.Framework;

namespace CamHelper.Tests.Interpreter
{
    [TestFixture]
    public class CalculatorTest
    {

        #region Operationstypen

        [Test]
        public void Addition()
        {
            var cmd = "1+2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("3", result);
        }

        [Test]
        public void Subtraction()
        {
            var cmd = "3-2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void Multiplication()
        {
            var cmd = "2*3";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("6", result);
        }

        [Test]
        public void Division()
        {
            var cmd = "6/2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("3", result);
        }

        [Test]
        public void Remainder()
        {
            var cmd = "13%5";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("3", result);
        }

        [Test]
        public void LessThan_True()
        {
            var cmd = "1<2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void LessThan_False()
        {
            var cmd = "2<1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("0", result);
        }

        [Test]
        public void GreaterThan_True()
        {
            var cmd = "2>1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void GreaterThan_False()
        {
            var cmd = "1>2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("0", result);
        }

        [Test]
        public void LessThanOrEqual_TrueE()
        {
            var cmd = "1<=1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void LessThanOrEqual_True()
        {
            var cmd = "1<=2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void LessThanOrEqual_False()
        {
            var cmd = "2<=1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("0", result);
        }

        [Test]
        public void GreaterThanOrEqual_True()
        {
            var cmd = "2>=1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void GreaterThanOrEqual_TrueE()
        {
            var cmd = "2>=2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void GreaterThanOrEqual_False()
        {
            var cmd = "1>=2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("0", result);
        }

        [Test]
        public void Equal_True()
        {
            var cmd = "1==1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void Equal_False()
        {
            var cmd = "1==2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("0", result);
        }

        [Test]
        public void NotEqual_True()
        {
            var cmd = "1!=2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void NotEqual_False()
        {
            var cmd = "1!=1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("0", result);
        }

        [Test]
        public void ConditionalAnd()
        {
            var cmd = "1&&1";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        [Test]
        public void ConditionalOr()
        {
            var cmd = "1||2";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("1", result);
        }

        #endregion

        [Test]
        public void Condition_True()
        {
            var cmd = "1==1?5:10";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("5", result);
        }

        [Test]
        public void Condition_False()
        {
            var cmd = "1==2?5:10";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("10", result);
        }

        [Test]
        public void ConditionInParentheses()
        {
            var cmd = "(1==1?5:10)";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("5", result);
        }

        [Test]
        public void Condition_Double()
        {
            var cmd = "1==2?5:(1==1?10:20)";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("10", result);
        }

        [Test]
        public void Parentheses()
        {
            var cmd = "(4+2)/3";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("2", result);
        }

        [Test]
        public void PointBeforeLine()
        {
            var cmd = "1+6/3";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("3", result);
        }

        [Test]
        public void DontSortLine()
        {
            var cmd = "88-33+55";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("110", result);
        }

        [Test]
        public void Parameter()
        {
            var cmd = "(tool.rad == 0) ? .global.path_type : 0";

            var parser = new Parser();
            parser.Parameter.Add(new Parameter("tool", "rad", "0"));
            parser.Parameter.Add(new Parameter("global", "path_type", "22"));
            var result = parser.Calc(cmd);

            Assert.AreEqual("22", result);
        }

        [Test]
        public void Parameter_UpperCase()
        {
            var cmd = "(Tool.Rad == 0) ? .Global.path_type : 0";

            var parser = new Parser();
            parser.Parameter.Add(new Parameter("tool", "rad", "0"));
            parser.Parameter.Add(new Parameter("global", "path_type", "22"));
            var result = parser.Calc(cmd);

            Assert.AreEqual("22", result);
        }

        [Test]
        public void NegativNumberAfterCondition()
        {
            var cmd = "(Tool.rad == 0) ? (Tool.diam > 30 ? -(Tool.diam * 0.15) : -(Tool.diam * 0.1)) : -(Tool.diam *.1 + Tool.rad)";

            var parser = new Parser();
            parser.Parameter.Add(new Parameter("tool", "rad", "0"));
            parser.Parameter.Add(new Parameter("tool", "diam", "10"));
            var result = parser.Calc(cmd);

            Assert.AreEqual("-1", result);
        }

        [Test]
        public void FunctionRound()
        {
            var cmd = "ROUND(1.234567,3)";

            var parser = new Parser();
            parser.Parameter.Add(new Parameter("tool", "diam", "1"));
            var result = parser.Calc(cmd);

            Assert.AreEqual("1.235", result);
        }

        [Test]
        public void ParameterWithFunctionRound()
        {
            var cmd = "ROUND((tool.diam*0.01),3)";

            var parser = new Parser();
            parser.Parameter.Add(new Parameter("tool", "diam", "2"));
            var result = parser.Calc(cmd);

            Assert.AreEqual("0.02", result);
        }

        [Test]
        public void ParameterWithFunctionRound2()
        {
            var cmd = "(tool.diam > 12) ? 0.15 : (tool.diam > 5 ? 0.1 : (tool.diam < 3 ? ROUND((tool.diam*0.01),3) : 0.05))";

            var parser = new Parser();
            var p = new Parameter("tool", "diam", "");
            parser.Parameter.Add(p);

            p.Value = "13";
            var result = parser.Calc(cmd);
            Assert.AreEqual("0.15", result);

            p.Value = "10";
            result = parser.Calc(cmd);
            Assert.AreEqual("0.1", result);

            p.Value = "6";
            result = parser.Calc(cmd);
            Assert.AreEqual("0.1", result);

            p.Value = "5";
            result = parser.Calc(cmd);
            Assert.AreEqual("0.05", result);

            p.Value = "2";
            result = parser.Calc(cmd);
            Assert.AreEqual("0.02", result);
        }

        [Test]
        public void Parameter_Nested()
        {
            var cmd = ".global.dpas";
            var input = new ParameterCollection();
            input.Add(new Parameter("Tool", "Diam", "24.88"));
            input.Add(new Parameter("Tool", "Rad", "2"));
            input.Add(new Parameter("global", "dpas", "(Tool.rad ==0 ) ? (Tool.diam *.75) : ((Tool.diam > 11) ? (Tool.diam - (Tool.rad * 2))* .75 : (Tool.diam - (Tool.rad * 2))* .9)"));

            var parser = new Parser();
            parser.Parameter.AddRange(input);
            var result = parser.Calc(cmd);

            Assert.AreEqual("15.66", result);
        }

        [Test]
        public void Empty()
        {
            var cmd = "";
            var result = Parser.StaticCalc(cmd);

            Assert.AreEqual("", result);
        }
    }
}
